<?php
/**################################################################################################**   
# Copyright (c)  2008  Carlos Galindo.   
# Permission is granted to copy, distribute and/or modify this document   
# under the terms of the GNU Free Documentation License, Version 1.2   
# or any later version published by the Free Software Foundation;   
# Provided 'as is' with no warranties, nor shall the autor be responsible for any mis-use of the same.     
# A copy of the license is included in the section entitled 'GNU Free Documentation License'.   
#   
#   CJAX FRAMEWORK 3.0.0RC2                $     
#   ajax made easy with cjax                    
#   -- DO NOT REMOVE THIS --                    
#   -- AUTHOR COPYRIGHT MUST REMAIN INTACT -   
#   CJAX FRAMEWORK  3.0.0RC2               $     
#   Written by: Carlos Galindo                  
#   Website: www.cjax.net                     $      
#   Email: cjxxi@msn.com    
#   Date: 2/12/2007                           $     
#   File Last Changed:  03/24/2009            $     
**####################################################################################################*/   

/**
 * Load core events
 */
require_once 'core.class.php';	
class CJAX_FRAMEWORK Extends CoreEvents {

	public $message_id;
	
	public public function auto_suggest($element,$url = null)
	{
		$this->xml("<element>$element</element><url>$url</url>");
	}
	
	public function insertBefore($element_id,$data=null,$class=null)
	{
		if($data && is_array($data)) {
			foreach($data as $k =>$v) {
				$d[] = "<cdata>{$this->encode($v)}</cdata>";
			}
			$data = implode($d);
		}
		$this->xml("<element>$element_id</element><data>{$this->encode($data)}</data>$class");		
	}
	
	/**
	 * Generally you would call a plugin thi way: ( supports unlimited paramameters)
	 * $CJAX->YourPluginName();
	 * 
	 * but this is an alternative, it only supports 3 parameters
	 *
	 * @param string $plugin_name
	 * @param string $param1
	 * @param string $param2
	 */
	public function plugin($plugin_name,$param1=null,$param2=null,$param3=null)
	{
		$this->xml("<name>$plugin_name</name><param1>$param1</param1><param2>$param2</param2><param3>$param3</param3>");
	}
	   
    /**
     * Executes an Ajax call and send a all the elements inside a form to the server in the $_GET method
     * 
     * @param require string $url
     * @param require string $form_id
     * @param optional string $container_id = null
     * @param optional string $mode = 'get'
     * @return unknown
     */
    public function form($url,$form_id,$container_id = null,$method='GET')
    {
        $CJAX = CJAX::getInstance();
        $params = '';
        $out[] = "<url>$url</url>";
        if($form_id) $out[] = "<form>$form_id</form>";
        if(!is_null($container_id)) $out[] = "<container>$container_id</container>";
        if($CJAX->text) $out[] = "<text>{$CJAX->text}</text>";
        if($CJAX->image) $out[] = "<image>{$CJAX->image_dir}{$CJAX->image}</image>";
        if($CJAX->debug) $out[] = "<dubug>1</debug>";   
        if($method) {
           $out[] = "<mode>$method</mode>";
        }
        return $this->xml("<do>exe_form</do><out>('".implode($out)."')</out>;");
    }
    
	public function form_js($url,$form=null,$container=null)
	{ 
		$event = "_event_";
		if($this->JSevent) {
			$event = "{$this->JSevent}=\"_event_\"";
		}
		$js = $this->form($url,$form,$container);
		return str_replace("_event_",$js,$event);
	}    
    
    /**
	 * Create Ajax calls
	 *
	 * @param required string $url
	 * @param optional string $elem_id = null
	 * @param optional string $cmode = 'get'
	 * @return string
	 */	
	public function call($url,$element_id='', $cmode = "get")
	{
		$CJAX = CJAX::getInstance();
		$out[] = "[url]{$url}[/url]";
		if($element_id) $out[] = "[element]{$element_id}[/element]";
		if($CJAX->text) $out[] = "[text]{$CJAX->text}[/text]";
		if ($CJAX->image) $out[] = "[image]{$CJAX->image}[/image]";
		if($cmode !='get') $out[] = "[mode]{$cmode}[/mode]";
		if ($CJAX->debug) $out[] = "[debug]1[/debug]";
		if(isset($out) && is_array($out)) $params = implode($out);
		return $this->xml("<do>exe_html</do><out>('{$params}')<out>");	
	}
	
	public function call_js($url,$element='')
	{ 
		$event = "_event_";
		if($this->JSevent) {
			$event = "{$this->JSevent}=\"_event_\"";
		}
		$js = $this->call($url,$element);
		return str_replace("_event_",$js,$event);
	}
	
	
	public function observe($element,$actions,$event="click",$flush = false)
	{
		$f = (($flush ===true)? "<event_flush>1</event_flush>":null);
		return $this->action($element,"<observe>".$actions."$f</observe>",$event);
	}
	
	
	/**
	 * evets:
	 * 
	 * click
	 * change
	 * keydown
	 * keypress
	 * 
	 * 
	 * @param $element
	 * @param $actions
	 * @param $event
	 * @return unknown_type
	 */
	public function action($element,$actions,$event="click")
	{
		if($actions && is_array($actions)) {
			foreach($actions as $k => $v) {
				if(is_array($v)) {
					foreach($v as $k2 => $v2) {
						$data[$k] = "<alt_element>$k</alt_element><alt_event>$k2</alt_event>".str_replace("do","_do_",$v2);//
					}
				} else {
					$data[$k] = str_replace("do","_do_",$v);
				}
			}
			$data = serialize($data);
			$data = str_replace(array("\"",";"),array("<sqt>","<sed>"),$data);
			$actions = "<array>$data</array>";
		} else {
			$actions = str_replace("do","_do_",$actions);
		}
		
		$data =  $this->AddEventTo($element,$actions,$event);
	
		$this->removeCache((is_array($actions)? count(array_keys($actions)) : 1 ));
		return $data;
	}
	
	public function select($element_id,$options = array(),$parent = null)
	{
		if($options) {
			$options = serialize($options);
			#die($options);
			$options = str_replace(array("\"",";"),array("<sqt>","<sed>"),$options);
		}
		//$this->_mkArray($elements)
		return $this->xml("<element>$element_id</element><array>$options</array><parent>$parent</parent>");
	}
	
	public function reset($element_id)
	{
		$this->xml("<element>$element_id</element>");
	}
		
	/**
	 * Execute an Ajax call "on the fly"
	 * 
	 * @param string $elem_id
	 * @param string $url
	 * @param string $mode
	 * @return an ajax call that will execute when  the page loads
	 */
	public function load($url,$elem_id, $mode = 'get')
	{
		$out[]="<url>$url</url>";
		if($elem_id) $out[] = "<element>{$elem_id}</element>";
		if($mode!='get') $out[] = "<mode>{$mode}</mode>";
		if($this->text) $out[] = "<text>{$this->text}</text>";
		if($this->image) $out[] = "<image>{$this->image_dir}{$this->image}</image>";
		if($this->debug) $out[] = "<dubug>1</debug>";	
		
		
		if(isset($out) && is_array($out)) {
			$params  = implode($out);
		}
		
		$script = "
		<script>
			CJAX.exe_html ('{$params}');
		</script>
		";

		return $script;
	}

	/**
	 * Just like form() , but this function is optimized to be loaded on the fly
	 *
	 * @param unknown_type $url
	 * @param unknown_type $form_id
	 * @param unknown_type $container_id
	 * @param unknown_type $mode
	 * @return unknown
	 */
	public function callEvent($url,$element_id = null)
	{
		$out[] = "<url>$url</url>";
		if($element_id) $out[] = "<element>{$element_id}</element>";
		if($this->text) $out[] = "<text>{$this->text}</text>";
		if ($this->image) $out[]  = "<image>$this->image</image>";
		if(isset($cmode)) $out[] = "<mode>$cmode</mode>";
		if ($this->debug) $out[] = "<debug>true</debug>";
		if(isset($out) && is_array($out)) $params  = implode($out);
		$return = "('{$params}')";
		$return ="CJAX.exe_html".$return.";";
		return $return;
	}
	
	public function addCallEvent($element,$url)
	{
		$this->AddEventTo($element,$this->encode($this->callEvent($url)),'addCallEvent','click');
	}
	
	/**
	 * Create Ajax calls
	 *
	 * @param required string $url
	 * @param optional string $elem_id = null
	 * @param optional string $cmode = 'get'
	 * @return string
	 */
	public function call_server($url,$element_id, $cmode = "get")
	{
		if($elem_id) $out[] = "<element>{$element_id}</element>";
		if($this->text) $out[] = "<text>{$this->text}</text>";
		if ($this->image) $out[]  = "<image>$this->image</image>";
		if($cmode !='get') $out[] = "<mode>$cmode</mode>";
		if ($this->debug) $out[] = "<debug>true</debug>";
		if(isset($out) && is_array($out)) $params  = implode($out);
		$this->xml("<url>$url</url>$params");
	}
	
	/**
	 * Set debug mode on/off
	 *
	 */
	public function debug($on=true)
	{
		$this->xml("<debug>".(($on)? 1:0)."</debug>");
	}
	
	/**
	 * set the focus to an element
	 *
	 * var $element_id
	 */
	public function focus($element_id)
	{
		$this->xml("<element>$element_id</element>");
	}
	
	/**
	 * Display a message in the middle of the screen
	 *
	 * @param string $data
	 * @param integer $seconds if specified, this is the number of seconds the message will appear in the screen
	 * then it will dissapear.
	 */
	public function message($data,$seconds=0,$id='cjax_message')
	{
		$data = $this->encode($data);
		ob_start();
		flush();
		flush();
		return $this->xml("<data>$data</data>".(($seconds)?"<time>{$seconds}</time>":"")."<element>$id</element>");
	
	}
	
	public function auto_complete($element,$elements = array())
	{
		return $this->xml("<element>$element</element><elements>".$this->_mkArray($elements)."</elements>");
	}
	
	private function _mkArray($array)
	{
		$new_array = null;
		if(!empty($array)) {
			foreach($array as $k =>$v) {
				$new_array[] = "<arr><k>$k</k><v>$v</v></arr>";
			}
		}
		$new_array = (($new_array)? implode($new_array) : null);
		return $new_array;
	}
	
	/**
	 * Send a click event to an element
	 *
	 * @param string $element_id
	 */
	public function click($element_id)
	{
		$this->xml("<element>$element_id</element>");
	}
	
	/**
	 * Create a dinamic textbox on using dom.
	 *
	 * @param string $element
	 * @param string $parent
	 * @param string $label
	 * @param string $value
	 * @param string $class
	 * @return TextBox
	 */
	public function textbox($new_textbox_id,$element_parent,$label='',$value='',$class='')
	{
		$this->xml("<element>$new_textbox_id</element><parent>$element_parent</parent><label>$label</label><value>$value</value><class>$class</class>");
	}
	
	/**
	 * Add event to elements
	 * --
	 * AddEventTo();
	 * 
	 * @param string $element
	 * @param string $event
	 * @param string $method
	 */
	public function AddEventTo($element,$action,$event='onclick')
	{
		$action = $this->encode($action);
		return $this->xml("<element_event>$element</element_event><event_method>$action</event_method><event_action>$event</event_action>");
	}
	
	/**
	 * An alian for AddEventTo
	 *
	 * @param string $element
	 * @param string $event
	 * @param string $method
	 */
	public function setEvent($element,$event='onload',$method ='')	
	{
		$this->AddEventTo($element,$event,$method);
	}
	
/*	*//**
	 * When checking for inputs on the back-end to return a user friendly-error
	 * use invalidate, this function is to highlight a specified text element if the input does not validate
	 * 
	 *
	 * @param string $elem [ELEMENT ID]
	 *//*
	function invalidate($element_id,$data='')
	{
		$data = $this->encode($data);
		$this->xml("<element>$element_id</element><error>$data</error>");
	}*/
	
	/**
	 * Apply a CSS defined class to elements which  contains a specified type
	 * such as "text" or "checkbox", "password"
	 *
	 * @param string $type
	 * @param string $class
	 * @param string $tag
	 */
	public function applyClassToType($type,$class,$tag = null)
	{
		$this->xml("<type>$type</type><class>$class</class><tag>$tag</tag>");	
	}
	
	/**
	 * Apply a CSS class to any elements of the page specifying a tag 
	 * for example  "input" will apply that class to all elements input in the page
	 *
	 * @param string $tag
	 * @param string $class
	 */
	public function applyClass($tag,$class)
	{
		$this->xml("<elem_tag>$tag</elem_tag><class>$class</class>");
	}
	
	/**
	 * Hide any element on the page
	 *
	 * @param string $element_id
	 */
	public function hide($element_id)
	{
		$this->xml("<element>$element_id</element>");
	}
	
	/**
	 * creates an html element on the page
	 * @param string $element_id
	 * @param string $type
	 * @param string $parent
	 * @param string $class
	 * @param string $html
	 */
	public function create_element($element_id,$parent='',$type='div',$html='',$class='')
	{
		$this->xml("<element>{$element_id}</element><parent>{$parent}</parent><class>{$class}</class><type>{$type}</type><data>{$this->encode($html)}</data>");
	}
	
	/**
	 * *set value to an element
	 * Usage: $CJAX->set_value('element_id','Hello World');
	 * @param string $element_id
	 * @param string $value
	 */
	public function set_value($element,$value='',$dynamic=false,$select_text=false)
	{
		$this->xml("<element>{$element}</element><value>{$this->encode($value)}</value>".(($dynamic)?"<dyna>1</dyna>":"").(($select_text)?"<select>1</select>":""));
	}
	
	
	/**
	 * This function is to get content of files or send large amount of data
	 *
	 */
	public function updateContent($element,$data,$itsSource=false)
	{
		if($itsSource) $data  = $this->syntax_hilight($data);
		$data = urlencode($data);
		$this->xml("<element>$element</element><data>$data</data>");
	}
	
	/**
	 * Update any element on the page by specifying the element ID
	 * Usage:  $CJAX->hide('element_id');
	 * @param string $obj
	 * @param string $data
	 */
	public function update($obj,$data=null)
	{
		$data = $this->encode( $data );
		$this->xml("<element>$obj</element><data>$data</data>");
	}
	
	/**
	 * Will execute a command in a specified amouth of time
	 * e.g $CJAX->wait(5);
	 * Will wait 5 seconds before executes the next CJAX command
	 * 
	 * @param integer $seconds
	 */
	
	public function wait($seconds)
	{
		if(!$seconds) {
			return false;
		}
		$this->xml("<seconds>{$seconds}</seconds>");
	}
	
	/**
	 * This is an alias for remove function.
	 * will remove an specified element from the
	 * page.
	 *
	 * @param string $obj
	 */
	public function destroy($obj)
	{
		$this->remove($obj);
	}
	
	/**
	 * Will remove an specified element from the page
	 *
	 * @param string $obj
	 */
	public function remove($obj)
	{
		 $this->xml("<do>remove</do><element>$obj</element>");
	}

	/**
	 * Redirect the page.
	 * this is a recommended alternative to the built-in php function Header(); 
	 * 
	 * @param string $where [URL]
	 */
	public function location($where = "")
	{
		 $this->xml("<url>$where</url>");
	}
	
	/**
	 * Alert a message
	 *
	 * @param string $message
	 */
	public function alert($message)
	{
		$message = $this->encode($message);
		return $this->xml("<msg>$message</msg>");
	}
	
	/**
	 * deprecated
	 * will load a page on the "fly"
	 *
	 * @param string $element
	 * @param string $page
	 */
	public function loadpage($element,$page)
	{
		$this->xml("<element>$element</element><page>$page</page>");
	}
	
	/**
	 * Will execute a javascript function
	 *
	 * @param string $function_name
	 * @param string $params
	 */
	public function load_function($function_name,$params='source')
	{
		$this->xml("<function>$function_name</function><param>$params</param>");
	}
	
	/**
	 * Will dynamically load external javascript files into the page, hiding the source code.
	 *
	 * @param string $path
	 * @param optional string $append_tag
	 */
	public function load_script($src,$use_domain = false)
	{
		if($use_domain){
			$use_domain ='__domain__';
		} else {
			$use_domain = '';
		}
		$this->xml("<script>$use_domain/$src</script>");
	}
	
	/**
	 * deprecated
	 * a quick way to make ajax calls
	 *
	 * @param string $element_id
	 * @param string $url
	 * @param string $mode
	 */
	public function fire_page($element_id, $url, $mode = 'get')
	{
		$this->xml("<element>$element_id</element><url>$url</url><mode>$mode</mode><text>Loading..</text><skiploop>true</skiploop>");
	}
	
	/**
	 * deprecated
	 * used with the old wait() method to execute delayed functionalities
	 * @param string $function_name
	 * @param string $params
	 * @return unknown
	 */
	public function load_method($function_name,$params='')
	{
		return "<function>$function_name</function><param>$params</param>";
	}
	
	/**
	 * Get the value on any html element such as inputs, text, checkbox, radio buttons, select elements
	 *
	 * @param string $element_id
	 * @return string
	 */
	public function value($element_id)
	{
		return "[$element_id]";
	}
}